#include <memory.h>

#include "icq_packet.h"



/*
--- FLAP_HEADER --------------
magik				2A
channel				xx
seq_num				xxxx
data_size			xxxx
------------------------------
--- SNAC_HEADER --------------
fam_id				xxxx
fam_sub				xxxx
flags				xxxx
reqest id			xxxxxxxx
------------------------------
*/


void init_packet( icq_packet_t * pk, UINT8 channel, UINT16 seq_num, UINT16 size )
{
	if ( pk->buf != NULL ) {
		suFreeMem(pk->buf);
		pk->buf = NULL;
		pk->ptr = NULL;
	}
	pk->mag = FLAP_MAGIK;
	pk->chan = channel;
	pk->seq_num = seq_num;
	pk->size = 0;
	pk->size2 = 0;
	if ( size > 0 ) {
		pk->buf = suAllocMem(size, NULL);
		pk->ptr = pk->buf;
	}
}
void free_packet( icq_packet_t * pk )
{
	if ( pk->buf )
		suFreeMem(pk->buf);
	pk->buf = NULL;
	pk->ptr = NULL;
}

void packByte( icq_packet_t * pk, BYTE val )
{
	pk->buf[pk->size++] = val;
}
void packWord( icq_packet_t * pk, WORD val )
{
	pk->buf[pk->size++] = val >> 8;
	pk->buf[pk->size++] = val;
}
void packDWord( icq_packet_t * pk, DWORD val )
{
	pk->buf[pk->size++] = val >> 24;
	pk->buf[pk->size++] = val >> 16;
	pk->buf[pk->size++] = val >> 8;
	pk->buf[pk->size++] = val;
}
void packArray( icq_packet_t * pk, const BYTE * buf, UINT16 len )
{
	while ( len-- )
		pk->buf[pk->size++] = *buf++;
}
void packTLV( icq_packet_t * pk, WORD type, WORD len, const BYTE * data )
{
	packWord(pk, type);
	packWord(pk, len);
	packArray(pk, data, len);
}
void packTLVByte( icq_packet_t * pk, WORD type, BYTE val )
{
	packWord(pk, type);
	packWord(pk, 0x01);
	packByte(pk, val);
}
void packTLVWord( icq_packet_t * pk, WORD type, WORD val )
{
	packWord(pk, type);
	packWord(pk, 0x02);
	packWord(pk, val);
}
void packTLVDWord( icq_packet_t * pk, WORD type, DWORD val )
{
	packWord(pk, type);
	packWord(pk, 0x04);
	packDWord(pk, val);
}

void packSNACHeader( icq_packet_t * pk, WORD fam, WORD sub, WORD flags, DWORD seq )
{
	packWord( pk, fam );
	packWord( pk, sub );
	packWord( pk, flags );
	packDWord( pk, seq );
}



void unpackByte( BYTE ** src, BYTE * dst )
{
	if ( dst ) {
		*dst = *(*src)++;
	} else {
		*src += 1;
	}
}
void unpackWord( BYTE ** src, WORD * dst )
{
	BYTE * tmp = *src;
	
	if ( dst ) {
		*dst  = *tmp++ << 8;
		*dst |= *tmp++;
		
		*src = tmp;
	} else {
		*src += 2;
	}
}
void unpackDWord( BYTE ** src, DWORD * dst )
{
	BYTE * tmp = *src;
	
	if ( dst ) {
		*dst  = *tmp++ << 24;
		*dst |= *tmp++ << 16;
		*dst |= *tmp++ << 8;
		*dst |= *tmp++;
		
		*src = tmp;
	} else {
		*src += 4;
	}
}

void unpackArray( BYTE ** src, BYTE * dst, UINT16 len )
{
	BYTE * tmp = *src;
	
	if ( dst ) {
		while (len--) {
			*dst++ = *tmp++;
		}
	} else
		tmp += len;
	
	*src = tmp;
}

void unpackString( BYTE ** src, char * str, UINT16 len )
{
	unpackArray(src, (BYTE *)str, len);
}

BOOL findTLVbyType( BYTE * buf, UINT16 len, UINT16 type )
{
	BYTE *	end = buf + len;
	WORD	tlv_type, tlv_len;
	
	while ( buf < end ) {
		unpackWord( &buf, &tlv_type );
		if ( tlv_type == type )
			return TRUE;
		unpackWord( &buf, &tlv_len );
		buf += tlv_len;
	}
	return FALSE;
}

BOOL packetIsFree( icq_packet_t * pk )
{
	return (pk->buf == NULL);
}
